package com.fastloan.core.apiauth.aop;

import com.alibaba.fastjson.JSON;
import com.fastloan.core.apiauth.anno.DecryptParam;
import com.fastloan.core.apiauth.base.service.impl.ry.model.RYRequestParam;
import com.fastloan.core.apiauth.service.EncryptUtil;
import com.kawins.result.ResultTo;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;

import static com.fastloan.core.apiauth.service.EncryptUtil.AGENT_ID;

/**
 * 加密aop
 *
 * @author yanwe
 * createTime 2018-01-2018/1/5 13:48
 */
@Aspect
@Component
public class EncryptAspect {

    private static final Logger logger = LoggerFactory.getLogger(EncryptAspect.class);

    @Pointcut("@annotation(com.fastloan.core.apiauth.anno.Encrypt)")
    public void EncryptAspect() {
    }

    @Around("EncryptAspect()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object needDecryptParam = null;
        Object[] args = joinPoint.getArgs();
        Annotation[][] methodAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < methodAnnotations.length; i++) {
            for (int j = 0; j < methodAnnotations[i].length; j++) {
                if (methodAnnotations[i][j] instanceof DecryptParam){
                    needDecryptParam = args[i];
                }
            }
        }
        if (needDecryptParam == null){
            return null;//解密失败或者方法参数未指定注解
        }
        Map<String, String> paramMap = BeanUtils.describe(needDecryptParam);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        RYRequestParam ryRequestParam = (RYRequestParam) request.getAttribute("ryRequestParam");
        ResultTo proceed = (ResultTo) joinPoint.proceed();
        logger.debug("返回信息："+ JSON.toJSONString(proceed));
        String result = EncryptUtil.ryEncrypt(ryRequestParam, paramMap.get(AGENT_ID), proceed);
        logger.debug("返回加密后信息："+ result);
        return result;
    }
}
